#ifndef _MICROBE_H_
#define _MICROBE_H_

#include <math_2d.h>

////////////////////////////////////////////////////////////////////////////////

#define SIM_MAX_PLAYERS 4
#define SIM_MAX_FOOD 64
#define SIM_MAX_MICROBES 1024

#define SIM_FOOD_VALUE 10
#define SIM_FOOD_TIME 2000
#define SIM_FOOD_RADIUS 4.0f
#define SIM_START_FOOD 150

#define SPEEDY_MICROBE_RADIUS 8.0f
#define SPEEDY_MICROBE_SIGHT_RADIUS 32.0f
#define SPEEDY_MICROBE_SPEED 60.0f
#define SPEEDY_MICROBE_TURN_SPEED 160.0f
#define SPEEDY_MICROBE_COST 1
#define SPEEDY_MICROBE_REPRODUCE_TIME 2000
#define SPEEDY_MICROBE_REPRODUCE_COST 20

#define SOLDIER_MICROBE_RADIUS 10.0f
#define SOLDIER_MICROBE_SIGHT_RADIUS 64.0f
#define SOLDIER_MICROBE_SPEED 40.0f
#define SOLDIER_MICROBE_TURN_SPEED 200.0f
#define SOLDIER_MICROBE_ATTACK_TIME 300
#define SOLDIER_MICROBE_RELOAD_TIME 300
#define SOLDIER_MICROBE_COST 2
#define SOLDIER_MICROBE_REPRODUCE_TIME 3000
#define SOLDIER_MICROBE_REPRODUCE_COST 30
#define SOLDIER_MICROBE_EVOLVE_TIME 2500
#define SOLDIER_MICROBE_EVOLVE_COST 10

#define BIG_DADDY_MICROBE_RADIUS 12.0f
#define BIG_DADDY_MICROBE_SIGHT_RADIUS 64.0f
#define BIG_DADDY_MICROBE_SPEED 10.0f
#define BIG_DADDY_MICROBE_RELOAD_TIME 2000
#define BIG_DADDY_MICROBE_COST 3
#define BIG_DADDY_MICROBE_EVOLVE_TIME 3000
#define BIG_DADDY_MICROBE_EVOLVE_COST 20

#define BULLET_RADIUS 2.0f
#define BULLET_SPEED 260.0f
#define BULLET_TIME ((BIG_DADDY_MICROBE_SIGHT_RADIUS - 1.05f * BIG_DADDY_MICROBE_RADIUS) / BULLET_SPEED)

#define SIM_EAT_TIME 5000

////////////////////////////////////////////////////////////////////////////////

struct Food
{
  unsigned id;
  bool alive;
  Vector2 pos;
};

struct Bullet
{
  Vector2 pos;
  float angle;
  float time;
  unsigned player_id;
  bool alive;
};

enum MicrobeType
{
  MICROBE_SPEEDY,
  MICROBE_SOLDIER,
  MICROBE_BIG_DADDY
};

enum MicrobeAction
{
  MICROBE_ACTION_NONE,
  MICROBE_ACTION_ATTACKING,
  MICROBE_ACTION_RELOADING,
  MICROBE_ACTION_REPRODUCING,
  MICROBE_ACTION_EVOLVING
};

struct Microbe
{
  MicrobeType type;
  unsigned id;
  unsigned player_id;
  Circle body;
  float angle;
  float sight;
  bool alive;
  MicrobeAction action;
  int action_time;
  LineSegment tentacle;
};

bool Microbe_canSoldierAttack(const Microbe* microbe, const Food* food);
bool Microbe_canSoldierAttack(const Microbe* microbe, const Microbe* enemy);

struct MicrobeOrder
{
  float turn;
  float move;
  float angle;
  bool attack;
  bool reproduce;
  bool evolve;
};

struct AIData
{
  Rectf bounds;
  int player_food;
  unsigned num_food;
  const Food* food[SIM_MAX_FOOD];
  unsigned num_microbes;
  const Microbe* microbe[SIM_MAX_MICROBES];
  unsigned num_enemies;
  const Microbe* enemy[SIM_MAX_MICROBES];
};

class AI
{
  public:
  virtual ~AI() {}
  
  virtual void think(const AIData& data, MicrobeOrder* order[SIM_MAX_MICROBES],
    int dM, float dT) = 0;
  virtual void thinkSpeedy(const AIData& data, MicrobeOrder* order, float dT) {};
};

typedef AI* (*AICreateFunc)();

#endif
